﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Threading;


namespace CCPSIP
{
  public class MSGKit
  {
    private const string kMSGKind = "iSender";
    private static System.Text.Encoding kMSGEncoding = System.Text.Encoding.GetEncoding("big5");
    private const int kConnTimeoutDefault = 5000;//ms
    private const string kIPAddrPattern = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";

    private const string kOracleServer = "MIS.CCP.COM.TW";
    private const string kOracleUserId = "AC";
    private static byte[] kOracleKey = { 0x54, 0x35, 0x30, 0x30, 0x31, 0x38, 0x35, 0x35 };

    private static string GetConnStrMIS() {
      return String.Format(
        "Data Source={0};Persist Security Info=True;User ID={1};Password={2}",
        kOracleServer, kOracleUserId, System.Text.Encoding.UTF8.GetString(kOracleKey));
    }


    /// <summary>
    /// 傳送 Windows CCP MSG 訊息(台北總公司) (new Thread)
    /// </summary>
    /// <param name="phoneNo">總公司分機號碼</param>
    /// <param name="message">訊息全文</param>
    public static void SendTextHQAsync(string phoneNo, string message) {
      CCPMsgParam paramObj = new CCPMsgParam(phoneNo, message);
      new Thread(new ParameterizedThreadStart(SendTextHQ)).Start(paramObj);
    }


    /// <summary>
    /// 執行 Windows CCP MSG 訊息傳送(台北總公司)
    /// </summary>
    /// <param name="param">CCPMsgParam參數物件</param>
    private static void SendTextHQ(object param) {
      if (!(param is CCPMsgParam)) {
        return;
      }

      OracleConnection connMIS = new OracleConnection(GetConnStrMIS());

      try {
        CCPMsgParam p = (CCPMsgParam)param;
        string phoneNo = p.PhoneNo;

        if (Regex.IsMatch(phoneNo, "^62[0-9]{3}$")) {
          phoneNo = phoneNo.Substring(2, 3);
        }
        else if (CCPSIP.SipKit.isHQMobileExt(phoneNo)) {
          phoneNo = CCPSIP.SipKit.getHQDesktopExt(phoneNo);
        }

        connMIS.Open();

        //【01】找出目標電腦的 IP 與 MSG Port
        //
        string selStr = "SELECT IP, PORT FROM IPPHONE_LOG"
          + " WHERE PHONE_AREA='62' AND PHONE_NO=:PHONE_NO"
          + " AND LOG_TIME>=TRUNC(SYSDATE-180)";
        OracleCommand selCmd = new OracleCommand(selStr, connMIS);
        selCmd.Parameters.Add("PHONE_NO", OracleType.VarChar).Value = phoneNo;
        OracleDataAdapter adapter = new OracleDataAdapter(selCmd);
        DataSet dataSet = new DataSet();
        adapter.Fill(dataSet);

        if (dataSet.Tables[0].Rows.Count > 0) {
          DataRow row = dataSet.Tables[0].Rows[0];
          string msgIP = Convert.ToString(row["IP"]);
          int msgPort = Convert.ToInt32(row["PORT"]);

          if (Regex.IsMatch(msgIP, kIPAddrPattern)) {
            //【02】Socket 連接目標電腦的 MSG
            //
            TcpClientWithTimeout tClient = new TcpClientWithTimeout(msgIP, msgPort, kConnTimeoutDefault);
            TcpClient clientSocket = tClient.Connect();
            NetworkStream serverStream = clientSocket.GetStream();
            serverStream.WriteTimeout = 2000;
            serverStream.ReadTimeout = 2000;


            //【03】調整跳脫字元
            //
            string tweakMsg = p.Message;
            tweakMsg = tweakMsg.Replace(",", "，");    //逗號會被當成換行，用全形替換
            tweakMsg = tweakMsg.Replace(" ", "　");    //空格不能傳，用全形替換
            tweakMsg = tweakMsg.Replace("&", "＆");    //"&"不能傳，用全形替換
            tweakMsg = tweakMsg.Replace("]: ", "]:\n");//文字訊息開頭當做第一行
            tweakMsg = tweakMsg.Replace("\n", ",");    //換行要用逗號表示


            //【04】依格式送出訊息
            //
            string fullParams = string.Format("Kind={0}&Hint={1}", kMSGKind, tweakMsg);
            byte[] cmdBytes = kMSGEncoding.GetBytes(fullParams);
            serverStream.Write(cmdBytes, 0, cmdBytes.Length);


            //【99】關閉 Socket 連線
            //
            serverStream.Close();
            clientSocket.Close();
            serverStream = null;
            clientSocket = null;
          }
        }
      }
      catch (Exception ex) {
        ChrisKit.SkipVar(ex);
      }
      finally {
        connMIS.Close();
      }
    }


    /// <summary>
    /// Windows CCP MSG 呼叫參數
    /// </summary>
    private class CCPMsgParam
    {
      private string _PhoneNo;
      private string _Message;

      public string PhoneNo { get { return this._PhoneNo; } }
      public string Message { get { return this._Message; } }


      public CCPMsgParam(string phoneNo, string message) {
        _PhoneNo = phoneNo;
        _Message = message;
      }
    }

  }
}
